package vip.web3.admin.sys.service.impl.biz;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.additional.query.impl.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import vip.web3.admin.common.utils.Query;
import vip.web3.admin.sys.dao.biz.ARecordDao;
import vip.web3.admin.sys.entity.biz.ARecordEntity;
import vip.web3.admin.sys.entity.biz.AUserWalletEntity;
import vip.web3.admin.sys.form.user.RecordEditForm;
import vip.web3.admin.sys.form.user.RecordPageForm;
import vip.web3.admin.sys.mapper.ARecordMapper;
import vip.web3.admin.sys.service.biz.IARecordService;
import vip.web3.admin.sys.service.biz.IAUserService;
import vip.web3.admin.sys.service.biz.IAUserWalletService;
import vip.web3.admin.sys.shiro.ShiroUtils;
import vip.web3.admin.sys.vo.biz.BizRecordVo;
import vip.web3.admin.sys.vo.biz.export.*;
import vip.web3.common.enums.AssetEnum;
import vip.web3.common.enums.OperateEnum;
import vip.web3.common.enums.RecordStatusEnum;
import vip.web3.common.exception.RRException;
import vip.web3.common.utils.Convert;
import vip.web3.common.utils.DateUtils;
import vip.web3.common.utils.PageUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 分红明细Service业务层处理
 * <p>
 * aut-horlilei
 *
 * @date 2024-09-27
 */
@Service
public class ARecordServiceImpl extends ServiceImpl<ARecordDao, ARecordEntity> implements IARecordService {

    @Resource
    private IAUserService iaUserService;

    @Resource
    private IAUserWalletService iAUserWalletService;

    /**
     * 批量删除分红明细
     *
     * @param ids 需要删除的分红明细主键
     * @return 结果
     */
    @Override
    public int deleteARecordByIds(String ids) {
        return this.baseMapper.deleteARecordByIds(Convert.toIntArray(ids));
    }

    @Override
    public List<ARecordEntity> listRechargeRecord() {
        QueryWrapper<ARecordEntity> query = new QueryWrapper();
        query.eq("type", OperateEnum.TYPE1.getType());
        query.eq("operate_type", AssetEnum.PAYMENT2.getCode());
        query.eq("status", AssetEnum.STATUS0.getCode());
        return baseMapper.selectList(query);
    }

    @Override
    public List<ARecordEntity> listWithdrawRecord() {
        QueryWrapper<ARecordEntity> query = new QueryWrapper();
        query.eq("type", OperateEnum.TYPE2.getType());
        query.eq("operate_type", AssetEnum.PAYMENT2.getCode());
        query.eq("status", AssetEnum.STATUS2.getCode());
        return baseMapper.selectList(query);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addRewardRecord(Integer userId,
                                String mobile,
                                Integer type,
                                String typeName,
                                String remark,
                                BigDecimal amount,
                                BigDecimal fee,
                                Integer operateType,
                                String address,
                                Integer status) {
        if (amount.compareTo(BigDecimal.ZERO) <= 0) {
            return;
        }
        ARecordEntity record = new ARecordEntity();
        record.setUserId(userId);
        record.setMobile(mobile);
        record.setType(type);
        record.setTypeName(typeName);
        record.setRemark(remark);
        record.setAmount(amount);
        record.setFee(fee);
        record.setOperateType(operateType);
        record.setStatus(status);
        record.setAddress(address);
        record.setCreateDate(new Date());
        record.setUpdateDate(new Date());
        baseMapper.insert(record);
    }

    @Override
    public PageUtils pageRecords(Map<String, Object> params, RecordPageForm form) {
        LambdaQueryChainWrapper<ARecordEntity> ad = getQueryWrapper(params, form);

        IPage<ARecordEntity> page = this.page(
                new Query<ARecordEntity>().getPage(params),
                ad.getWrapper()
        );
        List<BizRecordVo> recordVos = ARecordMapper.INSTANCE.toAdminBizRecordVoList(page.getRecords());
        if (!CollectionUtils.isEmpty(recordVos)) {
            for (BizRecordVo vo : recordVos) {
                vo.setName(iaUserService.getById(vo.getUserId()).getRealName());
            }
        }
        return new PageUtils(recordVos, page);
    }

    private @NotNull
    LambdaQueryChainWrapper<ARecordEntity> getQueryWrapper(Map<String, Object> params, RecordPageForm form) {
        LambdaQueryChainWrapper<ARecordEntity> ad = this.lambdaQuery();
        if ("flow".equals(params.get("record"))) {
            ad.ge(Objects.nonNull(form.getStartTime()), ARecordEntity::getCreateDate, form.getStartTime())
                    .le(Objects.nonNull(form.getEndTime()), ARecordEntity::getCreateDate, form.getEndTime())
                    .eq(Objects.nonNull(form.getType()), ARecordEntity::getType, form.getType())
                    .in(Objects.isNull(form.getType()), ARecordEntity::getType, OperateEnum.sysFlowTypes())
                    .eq(Objects.nonNull(form.getStatus()), ARecordEntity::getStatus, form.getStatus())
                    .and(StringUtils.isNotBlank(form.getKeyWord()),
                            wrapper -> wrapper.like(ARecordEntity::getMobile, form.getKeyWord())
                                    .or()
                                    .like(ARecordEntity::getUserId, form.getKeyWord()));
        } else {
            ad.ge(Objects.nonNull(form.getStartTime()), ARecordEntity::getCreateDate, form.getStartTime())
                    .le(Objects.nonNull(form.getEndTime()), ARecordEntity::getCreateDate, form.getEndTime())
                    .eq(Objects.nonNull(form.getType()), ARecordEntity::getType, form.getType())
                    .eq(Objects.nonNull(form.getOperateType()), ARecordEntity::getOperateType, form.getOperateType())
                    .in(Objects.isNull(form.getOperateType()), ARecordEntity::getOperateType, Lists.newArrayList(2, 3))
                    .eq(Objects.nonNull(form.getStatus()), ARecordEntity::getStatus, form.getStatus())
                    .and(StringUtils.isNotBlank(form.getKeyWord()),
                            wrapper -> wrapper.like(ARecordEntity::getMobile, form.getKeyWord())
                                    .or()
                                    .like(ARecordEntity::getUserId, form.getKeyWord()));
        }
        return ad.orderByDesc(ARecordEntity::getCreateDate);
    }

    @Override
    public List<ExRecordVo> exRecord(Map<String, Object> params, RecordPageForm form) {
        List<ARecordEntity> list = this.getQueryWrapper(params, form).list();
        List<BizRecordVo> recordVos = ARecordMapper.INSTANCE.toAdminBizRecordVoList(list);
        return ARecordMapper.INSTANCE.toExRecordVos(recordVos);
    }

    @Override
    public List<ExReCnyVo> exReCny(Map<String, Object> params, RecordPageForm form) {
        List<ARecordEntity> list = this.getQueryWrapper(params, form).list();
        List<BizRecordVo> recordVos = ARecordMapper.INSTANCE.toAdminBizRecordVoList(list);
        return ARecordMapper.INSTANCE.toExReCnyVos(recordVos);
    }

    @Override
    public List<ExReUsdtVo> exReUsdt(Map<String, Object> params, RecordPageForm form) {
        List<ARecordEntity> list = this.getQueryWrapper(params, form).list();
        List<BizRecordVo> recordVos = ARecordMapper.INSTANCE.toAdminBizRecordVoList(list);
        return ARecordMapper.INSTANCE.toEExReUsdtVos(recordVos);
    }

    @Override
    public List<ExCnyVo> exCny(Map<String, Object> params, RecordPageForm form) {
        List<ARecordEntity> list = this.getQueryWrapper(params, form).list();
        List<BizRecordVo> recordVos = ARecordMapper.INSTANCE.toAdminBizRecordVoList(list);
        if (!CollectionUtils.isEmpty(recordVos)) {
            for (BizRecordVo vo : recordVos) {
                vo.setName(iaUserService.getById(vo.getUserId()).getRealName());
            }
        }
        return ARecordMapper.INSTANCE.toExCnyVos(recordVos);
    }

    @Override
    public List<ExUsdtVo> exUsdt(Map<String, Object> params, RecordPageForm form) {
        List<ARecordEntity> list = this.getQueryWrapper(params, form).list();
        List<BizRecordVo> recordVos = ARecordMapper.INSTANCE.toAdminBizRecordVoList(list);
        return ARecordMapper.INSTANCE.toExUsdtVos(recordVos);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void edit(RecordEditForm form) {
        RecordStatusEnum formStatus = RecordStatusEnum.get(form.getStatus());
        if (!RecordStatusEnum.CLOSE.equals(formStatus)
                && !RecordStatusEnum.WAIT_CONFIRM.equals(formStatus)
                && !RecordStatusEnum.BACK.equals(formStatus)) {
            throw new RRException("状态非法!!", -1);
        }
        if (RecordStatusEnum.BACK.equals(formStatus) && StringUtils.isBlank(form.getReason())) {
            throw new RRException("退款原因不能空!!", -1);
        }
        ARecordEntity entity = this.baseMapper.selectById(form.getId());
        if (Objects.isNull(entity)) {
            throw new RRException("记录不存在!!", -1);
        }
        RecordStatusEnum entityStatus = RecordStatusEnum.get(entity.getStatus());
        if (!RecordStatusEnum.INIT.equals(entityStatus)) {
            throw new RRException("未结算状态才允许更改!!", -1);
        }

        Date date = new Date();
        String remark = String.format("%s, %s [%s] 状态由 %d[%s] 改为 %d[%s]",
                entity.getRemark(),
                DateUtils.format(date, DateUtils.DATE_TIME_PATTERN),
                ShiroUtils.getUserEntity().getUsername(),
                entity.getStatus(), entityStatus.getDesc(),
                form.getStatus(), formStatus.getDesc());
        entity.setRemark(remark);
        entity.setStatus(form.getStatus());
        entity.setUpdateDate(date);

        if (form.getStatus().intValue() == 4) {
            entity.setRemark(remark + ",退款原因：" + form.getReason());
            // 退款
            int operateType = entity.getOperateType().intValue();
            AUserWalletEntity wallet = iAUserWalletService.findByUserId(entity.getUserId());
            if (operateType == 1) {
                iAUserWalletService.updateWallet(wallet, AssetEnum.TYPE3.getCode(),
                        entity.getAmount(), BigDecimal.ZERO);
            } else {
                iAUserWalletService.updateWallet(wallet, AssetEnum.TYPE4.getCode(),
                        entity.getAmount(), BigDecimal.ZERO);
            }
        }
        this.baseMapper.updateById(entity);
    }
}
